<script setup lang="ts">
import { Delete } from '@element-plus/icons-vue'
import type { Action, FormInstance } from 'element-plus'

import { cloneDeep } from 'lodash-es'
import {
  defaultUnitFormData,
  formRules,
  resetFormData,
} from '../index'
import { getWorkerHours, isLessThanHour } from './'
import type {
  CustomDialogInstance,
  DeepPartial,
  SchedulingSaveOrUpdateShiftUnitParams,
  TableColumn,
} from '@/types'
import { saveOrUpdateShiftUnit } from '@/api/modules/scheduling'

defineProps<{
  title: string
}>()
const emits = defineEmits<{
  success: []
}>()
// ------------------use------------------
// #region
const { $confirm } = useCurrentInstance()
const { loading, withLoading } = useDefineLoading()
const formData = defineModel('data', {
  default: () => resetFormData(),
})
const [unitFormData, setUnitFormData] = useState({
  ...defaultUnitFormData,
})
const [tableData, setTableData] = useState<any[]>([])
const [isEdit, setIsEdit] = useState(false)
// #endregion
// ------------------静态变量------------------
// #region
const columns: TableColumn<any>[] = [
  {
    key: uuid(),
    label: '班次名称',
    prop: 'name',
  },
  {
    key: uuid(),
    label: '排班时间',
    width: '120px',
    render({ row }) {
      return `${row.startTime} - ${row.endTime}`
    },
  },
  {
    key: uuid(),
    label: '是否跨天',
    render({ row }) {
      return row.overnightShift ? '是' : '否'
    },
  },
  {
    key: uuid(),
    label: '工时',
    render({ row }) {
      const { hour, minute } = getWorkerHours(
        row.startTime,
        row.endTime,
        row.overnightShift,
      )
      return `${hour}时 ${minute}分`
    },
  },
]

const unitFormRules = generateCurrencyFormRules(
  defaultUnitFormData,
  [],
  {
    endTime: [
      {
        validator: (_: any, __: any, callback: any) =>
          validate(callback, 'end'),
        trigger: 'change',
      },
    ],
    startTime: [
      {
        validator: (_: any, __: any, callback: any) =>
          validate(callback, 'start'),
        trigger: 'change',
      },
    ],
  },
)
const startTimeId = `startTimeId${uuid()}`
const endTimeId = `endTimeId${uuid()}`
// #endregion
// ------------------动态变量------------------
// #region

// #endregion
// ------------------ref-----------
// #region
const dialogRef = ref<CustomDialogInstance | null>(null)
const formRef = ref<FormInstance | null>(null)
const unitFormRef = ref<FormInstance | null>(null)
// #endregion
// ------------------reactive------
// #region
// #endregion
// ------------------computed------
// #region
const computedHours = computed(() => {
  if (
    !unitFormData.value.startTime
    || !unitFormData.value.endTime
  ) {
    return '---'
  }
  const { hour, minute } = getWorkerHours(
    unitFormData.value.startTime,
    unitFormData.value.endTime,
    unitFormData.value.overnightShift,
  )
  return `${hour}时 ${minute}分`
})
const computedSelectHours = computed(() => {
  const o: number[] = []
  tableData.value.forEach((item) => {
    const start = +item.startTime.split(':')[0]!
    const end = +item.endTime.split(':')[0]!
    if (item.overnightShift) {
      o.push(
        ...[...range(start, 24)],
        ...[...range(1, end)],
      )
    }
    else {
      o.push(...[...range(Math.max(start, 1), end)])
    }
  })
  return [...new Set(o)]
})
// #endregion
// ------------------生命周期------------------
// #region

// #endregion
// ------------------内置方法---------------------
// #region
watch(
  () => formData.value.shiftList,
  (list: any) => {
    if (!list)
      return
    setTableData(cloneDeep(list))
  },
  {
    deep: true,
  },
)
watch(
  () => unitFormData.value.startTime,
  handleStartTimeChange,
)
watch(
  () => unitFormData.value.endTime,
  handleEndTimeChange,
)
// #endregion
// ------------------方法---------------------
// #region
function validate(
  callback: any,
  type: 'start' | 'end' = 'start',
) {
  const { startTime, endTime, overnightShift }
    = toValue(unitFormData)
  const current = formatTime(Date.now(), 'YYYY/MM/DD')
  const start = new Date(`${current} ${startTime!}`)
  const end = new Date(`${current} ${endTime!}`)
  // 判断工时小于一小时的情况
  if (startTime && endTime) {
    const isLessOneHour = isLessThanHour(
      1,
      overnightShift!,
      [startTime!, endTime!],
    )
    if (isLessOneHour) {
      callback(new Error('工时小于一小时'))
      return
    }
    // 判断总工时超过24小时的情况
    const isMoreThan24Hour = isDateOverflow(
      startTime!,
      endTime!,
      overnightShift!,
    )
    console.log('isMoreThan24Hour', isMoreThan24Hour)

    if (isMoreThan24Hour) {
      callback(new Error('排班总工时超过24小时'))
      return
    }
  }
  const [sh, sm] = (unitFormData.value.startTime! || '').split(':')
  // console.log(sh, sm, startTime);
  const [eh, em] = (unitFormData.value.endTime! || '').split(':')
  // console.log(eh, em, endTime);
  const presenceStartTime: string[] = []
  const presenceEndTime: string[] = []
  tableData.value.forEach((item) => {
    if (item.overnightShift) {
      presenceEndTime.push(item.startTime)
      presenceStartTime.push(item.endTime)
    }
    else {
      presenceEndTime.push(item.endTime)
      presenceStartTime.push(item.startTime)
    }
  })
  console.log('overnightShift', overnightShift)
  if (overnightShift) {
    // 处理跨天时

    // if (startTime && endTime) {
    //   // 处理时交叉
    //   const p = [
    //     ...range(+sh! + 1, 24),
    //     ...range(1, +eh! - 1),
    //   ]
    //   const c = p.some(item =>
    //     computedSelectHours.value.includes(item),
    //   )
    //   if (c) {
    //     callback(new Error('工作时间不能交叉'))
    //     return
    //   }
    // }

    // 处理分交叉
    if (type === 'start') {
      // 处理开始时间分交叉
      for (const time of presenceEndTime) {
        const [h, m] = (time || '').split(':')
        if (+sh! === +h! && +sm! < +m!) {
          callback(new Error('开始时间不能交叉'))
          return
        }
      }
      // 处理纰漏
      // if (computedSelectHours.value.includes(+sh!)) {
      //   callback(new Error('开始时间不能交叉'));
      //   return;
      // }
    }

    if (type === 'end') {
      // 处理结束时间分交叉
      for (const time of presenceStartTime) {
        const [h, m] = (time || '').split(':')
        if (+eh! === +h! && +em! > +m!) {
          callback(new Error('结束时间不能交叉'))
          return
        }
      }

      // 处理纰漏
      // if (computedSelectHours.value.includes(+eh!)) {
      //   callback(new Error('结束时间不能交叉'));
      //   return;
      // }
    }
  }
  else {
    // 不跨天情况
    if (startTime && endTime) {
      if (start.getTime() > end.getTime()) {
        callback(new Error('结束时间不能小于开始时间'))
        return
      }
      // 处理时交叉
      // const c = [...range(+sh!, +eh!)].some(item =>
      //   computedSelectHours.value.includes(item),
      // )
      // if (c) {
      //   callback(new Error('工作时间不能交叉'))
      //   return
      // }
    }

    // 处理分交叉
    if (type === 'start') {
      // 处理时交叉
      // if (computedSelectHours.value.includes(+sh!)) {
      //   callback(new Error('开始时间不能交叉'))
      //   return
      // }
      // 处理开始时间分交叉
      for (const time of presenceEndTime) {
        const [h, m] = (time || '').split(':')
        if (+sh! === +h! && +sm! < +m!) {
          callback(new Error('开始时间不能交叉'))
          return
        }
      }
    }

    if (type === 'end') {
      // 处理时交叉
      // if (computedSelectHours.value.includes(+eh!)) {
      //   callback(new Error('结束时间不能交叉'))
      //   return
      // }
      // 处理结束时间分交叉
      for (const time of presenceStartTime) {
        const [h, m] = (time || '').split(':')
        if (+eh! === +h! && +em! > +m!) {
          callback(new Error('结束时间不能交叉'))
          return
        }
      }
    }
  }
  callback()
}
/** 排班时间是否大于24小数 */
function isDateOverflow(startTime: string, endTime: string, overnightShift?: number) {
  const current = getWorkerHours(
    startTime,
    endTime,
    overnightShift,
  )
  const data = tableData.value.map(item =>
    getWorkerHours(
      item.startTime,
      item.endTime,
      item.overnightShift,
    ),
  )
  data.push(current)
  const h = data.reduce((pre, cur) => {
    const o = pre + cur.hour + cur.minute / 60
    return o
  }, 0)
  console.warn('h', h, typeof h)

  return h > 24 || Math.floor(h) > 24
}
async function open() {
  dialogRef.value?.open?.()
  await nextTick()
  dialogRef.value?.setSaving?.(false)
  formRef.value?.resetFields()
  unitFormRef.value?.resetFields()
  setIsEdit(false)
  setUnitFormData({ ...defaultUnitFormData })
}
async function close() {
  setTableData([])
  await nextTick()
  dialogRef.value?.close?.()
}
async function add() {
  const isValid = await unitFormRef.value?.validate()
  if (!isValid)
    return
  tableData.value.push(unitFormData.value)
  setUnitFormData({ ...defaultUnitFormData })
  setIsEdit(true)
}
async function clickConfirm(done: () => void) {
  try {
    if (unref(tableData).length === 0) {
      ElMessage.warning('请添加班次单元')
      done()
      return false
    }
    await formRef.value?.validate()
    await addOrUpdateData()
    setIsEdit(false)
    done()
    emits('success')
  }
  catch (error) {
    done()
  }
}
async function addOrUpdateData() {
  const list = cloneDeep(tableData.value)
  removeUnnecessaryParams(list)
  const info = cloneDeep(formData.value.shiftUnit)
  removeUnnecessaryParams(info!)
  const params: DeepPartial<SchedulingSaveOrUpdateShiftUnitParams>
    = { shiftUnit: info, shiftList: list }
  await withLoading(saveOrUpdateShiftUnit)(params)
}
async function handleBeforeClose(done: () => void) {
  if (isEdit.value) {
    const res: Action = await $confirm(
      '数据发生更改，确定关闭？',
      '警告',
      {
        type: 'warning',
      },
    ).catch(e => e)

    if (res !== 'confirm')
      return
  }
  done()
}
async function deleteData(index: number) {
  const res: Action = await $confirm(
    '该操作将删除该数据，确定删除？',
    '警告',
    {
      type: 'warning',
    },
  ).catch(e => e)

  if (res !== 'confirm')
    return
  tableData.value.splice(index, 1)
  setIsEdit(true)
}
function handleStartTimeChange(
  newVal?: string,
  oldVal?: string,
) {
  if (!newVal || !oldVal)
    return
  const [nh, nm] = newVal.split(':')
  const [oh] = oldVal.split(':')
  if (nh !== oh && nm !== '00') {
    const target = document.querySelectorAll(
      `.el-popper.${startTimeId} .el-scrollbar__wrap`,
    )[1]!

    unitFormData.value.startTime = `${nh}:00`
    target?.scrollTo?.(0, 0)
  }
}
function handleEndTimeChange(
  newVal?: string,
  oldVal?: string,
) {
  if (!newVal || !oldVal)
    return
  const [nh, nm] = newVal.split(':')
  const [oh] = oldVal.split(':')
  if (nh !== oh && nm !== '00') {
    const target = document.querySelectorAll(
      `.el-popper.${endTimeId} .el-scrollbar__wrap`,
    )[1]!
    unitFormData.value.endTime = `${nh}:00`
    target?.scrollTo?.(0, 0)
  }
}
// #endregion
defineExpose({
  open,
  close,
})
</script>

<template>
  <CustomDialog
    ref="dialogRef"
    :title="title"
    need-saving
    width="940px"
    :before-close="handleBeforeClose"
    @confirm="clickConfirm"
  >
    <div
      class="align-center height-vh-1/3 flex gap-col-xs container"
    >
      <div
        class="width-3/5 height-fill flex-direction flex"
      >
        <view-table
          border
          :columns="columns"
          :show-toolbox="false"
          :data="tableData"
        >
          <template #operate="{ index }">
            <TdButton
              title="删除"
              :icon="Delete"
              type="danger"
              @click="deleteData(index)"
            />
          </template>
        </view-table>
      </div>
      <div class="width-2/5 height-fill">
        <el-form
          ref="formRef"
          label-width="120px"
          label-position="right"
          :model="formData.shiftUnit"
          :rules="formRules"
          inline
        >
          <el-form-item
            label="班次单元名称"
            prop="name"
            class="width-fill"
          >
            <el-input
              v-model.trim="formData.shiftUnit!.name"
              maxlength="10"
              placeholder="请输入名称"
              class="free"
            />
          </el-form-item>
        </el-form>
        <el-form
          ref="unitFormRef"
          label-width="80px"
          label-position="right"
          :model="unitFormData"
          :rules="unitFormRules"
        >
          <fieldset
            class="flex-direction margin-0 flex align-end"
          >
            <legend class="padding-lr-sm text-bold">
              班次
            </legend>
            <el-form-item
              label="班次名称"
              prop="name"
              class="width-fill"
            >
              <el-input
                v-model.trim="unitFormData.name"
                maxlength="10"
                placeholder="请输入名称"
              />
            </el-form-item>
            <el-form-item
              label="是否跨天"
              class="width-fill"
            >
              <div class="align-center width-fill flex">
                <el-checkbox
                  v-model="unitFormData.overnightShift"
                  :true-label="1"
                  :false-label="0"
                  label="跨天"
                />
                <span class="margin-left-auto">
                  工时：{{ computedHours }}
                </span>
              </div>
            </el-form-item>
            <div
              class="width-fill align-center flex gap-sm"
            >
              <el-form-item label="时间" prop="startTime">
                <el-time-picker
                  v-model="unitFormData.startTime"
                  placeholder="开始时间"
                  class="free"
                  format="HH:mm"
                  value-format="HH:00"
                  :popper-class="`${startTimeId} no-minute`"
                  style="width: 120px"
                />
              </el-form-item>
              <el-form-item prop="endTime" label-width="0">
                <el-time-picker
                  v-model="unitFormData.endTime"
                  placeholder="结束时间"
                  class="free"
                  format="HH:mm"
                  value-format="HH:00"
                  :popper-class="`${endTimeId} no-minute`"
                  style="width: 120px"
                />
              </el-form-item>
            </div>
            <el-button
              type="primary"
              class="width-max-content"
              @click="add"
            >
              新增
            </el-button>
          </fieldset>
        </el-form>
      </div>
    </div>
    <!-- <template #footer>
      <span class="dialog-footer">
        <ElButton @click="handleBeforeClose">取消</ElButton>
        <ElButton
          type="primary"
          :loading="loading"
          @click="clickSave"
        >
          保存
        </ElButton>
      </span>
    </template> -->
  </CustomDialog>
</template>

<style lang="scss">
.no-minute {
  .el-time-spinner__wrapper {
    width: 100%;
    &:last-child {
      display: none;
    }
  }
}
</style>
